﻿#pragma once
#include "yzrutil.h"
#include "DSP.h"
#include "BufferDelayer.h"

namespace yzrilyzr_dsp{
	ECLASS(Delayer, public DSP){
	private:
	RingBufferSample buffer;
	u_sample delayIndex=0;
	public:
	u_time_ms delayTimeMs=0;
	u_normal_11 feedback=0;
	u_normal_01 wetRatio=0;
	BufferDelayer::DelayFunction delayFunction=BufferDelayer::linearDelay;
	Delayer();
	/**
	 * @param delay  毫秒
	 * @param reverb 衰减[0, 1]
	 * @param mix    湿声比例[0, 1]
	 */
	Delayer(u_time_ms delayTimeMs, u_normal_11 feedback, u_normal_01 wetRatio) : delayTimeMs(delayTimeMs), feedback(feedback), wetRatio(wetRatio){}
	u_sample procDsp(u_sample v)override{
		if(delayTimeMs == 0 || delayIndex <= 0) return v;
		u_sample delayed=delayFunction(buffer, delayIndex);
		buffer.write((v + delayed) * feedback);
		return delayed * wetRatio + v * (1 - wetRatio);
	}
	void init(u_sample_rate sampleRate)override{
		delayIndex=RingBufferUtil::ms2DelayIndex(delayTimeMs, sampleRate);
		buffer.ensureCapacity(delayIndex);
	}
	void resetMemory()override{
		buffer.fill(0);
	}
	std::shared_ptr<DSP> cloneDSP()override{
		return std::make_shared < Delayer>(delayTimeMs, feedback, wetRatio);
	}
	void cloneParam(DSP * obj1)override{
		if(auto other=dynamic_cast<Delayer *>(obj1)){
			wetRatio=other->wetRatio;
			delayTimeMs=other->delayTimeMs;
			feedback=other->feedback;
			delayFunction=other->delayFunction;
		}
	}
	yzrilyzr_lang::String toString()const override;
	};
}